use crate::src::struct_and_type::{
    SListCompareFunc, SListEntry, SListEqualFunc, SListIterator, SListValue,
};

extern "C" {
    fn malloc(_: u64) -> *mut ();
    fn free(_: *mut ());
}
#[no_mangle]
pub extern "C" fn slist_free(mut list: *mut SListEntry) {
    let mut entry: *mut SListEntry = 0 as *mut SListEntry;
    entry = list;
    while !entry.is_null() {
        let mut next: *mut SListEntry = 0 as *mut SListEntry;
        next = unsafe { (*entry).next };
        (unsafe { free(entry as *mut ()) });
        entry = next;
    }
}
#[no_mangle]
pub extern "C" fn slist_prepend(
    mut list: *mut *mut SListEntry,
    mut data: SListValue,
) -> *mut SListEntry {
    let mut newentry: *mut SListEntry = 0 as *mut SListEntry;
    newentry = (unsafe { malloc(::core::mem::size_of::<SListEntry>() as u64) }) as *mut SListEntry;
    if newentry.is_null() {
        return 0 as *mut SListEntry;
    }
    (unsafe { (*newentry).data = data });
    (unsafe { (*newentry).next = *list });
    (unsafe { *list = newentry });
    return newentry;
}
#[no_mangle]
pub extern "C" fn slist_append(
    mut list: *mut *mut SListEntry,
    mut data: SListValue,
) -> *mut SListEntry {
    let mut rover: *mut SListEntry = 0 as *mut SListEntry;
    let mut newentry: *mut SListEntry = 0 as *mut SListEntry;
    newentry = (unsafe { malloc(::core::mem::size_of::<SListEntry>() as u64) }) as *mut SListEntry;
    if newentry.is_null() {
        return 0 as *mut SListEntry;
    }
    (unsafe { (*newentry).data = data });
    (unsafe { (*newentry).next = 0 as *mut SListEntry });
    if (unsafe { *list }).is_null() {
        (unsafe { *list = newentry });
    } else {
        rover = unsafe { *list };
        while !(unsafe { (*rover).next }).is_null() {
            rover = unsafe { (*rover).next };
        }
        (unsafe { (*rover).next = newentry });
    }
    return newentry;
}
#[no_mangle]
pub extern "C" fn slist_data(mut listentry: *mut SListEntry) -> SListValue {
    return unsafe { (*listentry).data };
}
#[no_mangle]
pub extern "C" fn slist_set_data(mut listentry: *mut SListEntry, mut data: SListValue) {
    if !listentry.is_null() {
        (unsafe { (*listentry).data = data });
    }
}
#[no_mangle]
pub extern "C" fn slist_next(mut listentry: *mut SListEntry) -> *mut SListEntry {
    return unsafe { (*listentry).next };
}
#[no_mangle]
pub extern "C" fn slist_nth_entry(mut list: *mut SListEntry, mut n: u32) -> *mut SListEntry {
    let mut entry: *mut SListEntry = 0 as *mut SListEntry;
    let mut i: u32 = 0;
    entry = list;
    i = 0 as u32;
    while i < n {
        if entry.is_null() {
            return 0 as *mut SListEntry;
        }
        entry = unsafe { (*entry).next };
        i = i.wrapping_add(1);
        i;
    }
    return entry;
}
#[no_mangle]
pub extern "C" fn slist_nth_data(mut list: *mut SListEntry, mut n: u32) -> SListValue {
    let mut entry: *mut SListEntry = 0 as *mut SListEntry;
    entry = slist_nth_entry(list, n);
    if entry.is_null() {
        return core::ptr::null_mut();
    } else {
        return unsafe { (*entry).data };
    };
}
#[no_mangle]
pub extern "C" fn slist_length(mut list: *mut SListEntry) -> u32 {
    let mut entry: *mut SListEntry = 0 as *mut SListEntry;
    let mut length: u32 = 0;
    length = 0 as u32;
    entry = list;
    while !entry.is_null() {
        length = length.wrapping_add(1);
        length;
        entry = unsafe { (*entry).next };
    }
    return length;
}
#[no_mangle]
pub extern "C" fn slist_to_array(mut list: *mut SListEntry) -> *mut SListValue {
    let mut rover: *mut SListEntry = 0 as *mut SListEntry;
    let mut array: *mut SListValue = 0 as *mut SListValue;
    let mut length: u32 = 0;
    let mut i: u32 = 0;
    length = slist_length(list);
    array = (unsafe {
        malloc((::core::mem::size_of::<SListValue>() as u64).wrapping_mul(length as u64))
    }) as *mut SListValue;
    if array.is_null() {
        return 0 as *mut SListValue;
    }
    rover = list;
    i = 0 as u32;
    while i < length {
        let fresh0 = unsafe { &mut (*array.offset(i as isize)) };
        *fresh0 = unsafe { (*rover).data };
        rover = unsafe { (*rover).next };
        i = i.wrapping_add(1);
        i;
    }
    return array;
}
#[no_mangle]
pub extern "C" fn slist_remove_entry(
    mut list: *mut *mut SListEntry,
    mut entry: *mut SListEntry,
) -> i32 {
    let mut rover: *mut SListEntry = 0 as *mut SListEntry;
    if (unsafe { *list }).is_null() || entry.is_null() {
        return 0;
    }
    if (unsafe { *list }) == entry {
        (unsafe { *list = (*entry).next });
    } else {
        rover = unsafe { *list };
        while !rover.is_null() && (unsafe { (*rover).next }) != entry {
            rover = unsafe { (*rover).next };
        }
        if rover.is_null() {
            return 0;
        } else {
            (unsafe { (*rover).next = (*entry).next });
        }
    }
    (unsafe { free(entry as *mut ()) });
    return 1;
}
#[no_mangle]
pub extern "C" fn slist_remove_data(
    mut list: *mut *mut SListEntry,
    mut callback: SListEqualFunc,
    mut data: SListValue,
) -> u32 {
    let mut rover: *mut *mut SListEntry = 0 as *mut *mut SListEntry;
    let mut next: *mut SListEntry = 0 as *mut SListEntry;
    let mut entries_removed: u32 = 0;
    entries_removed = 0 as u32;
    rover = list;
    while !(unsafe { *rover }).is_null() {
        if (unsafe { callback.expect("non-null function pointer")((**rover).data, data) })
            != 0
        {
            next = unsafe { (**rover).next };
            (unsafe { free(*rover as *mut ()) });
            (unsafe { *rover = next });
            entries_removed = entries_removed.wrapping_add(1);
            entries_removed;
        } else {
            rover = unsafe { &mut (**rover).next };
        }
    }
    return entries_removed;
}
extern "C" fn slist_sort_internal(
    mut list: *mut *mut SListEntry,
    mut compare_func: SListCompareFunc,
) -> *mut SListEntry {
    let mut pivot: *mut SListEntry = 0 as *mut SListEntry;
    let mut rover: *mut SListEntry = 0 as *mut SListEntry;
    let mut less_list: *mut SListEntry = 0 as *mut SListEntry;
    let mut more_list: *mut SListEntry = 0 as *mut SListEntry;
    let mut less_list_end: *mut SListEntry = 0 as *mut SListEntry;
    let mut more_list_end: *mut SListEntry = 0 as *mut SListEntry;
    if (unsafe { *list }).is_null() || (unsafe { (**list).next }).is_null() {
        return unsafe { *list };
    }
    pivot = unsafe { *list };
    less_list = 0 as *mut SListEntry;
    more_list = 0 as *mut SListEntry;
    rover = unsafe { (**list).next };
    while !rover.is_null() {
        let mut next: *mut SListEntry = unsafe { (*rover).next };
        if (unsafe {
            compare_func.expect("non-null function pointer")((*rover).data, (*pivot).data)
        }) < 0
        {
            (unsafe { (*rover).next = less_list });
            less_list = rover;
        } else {
            (unsafe { (*rover).next = more_list });
            more_list = rover;
        }
        rover = next;
    }
    less_list_end = slist_sort_internal(&mut less_list, compare_func);
    more_list_end = slist_sort_internal(&mut more_list, compare_func);
    (unsafe { *list = less_list });
    if less_list.is_null() {
        (unsafe { *list = pivot });
    } else {
        (unsafe { (*less_list_end).next = pivot });
    }
    (unsafe { (*pivot).next = more_list });
    if more_list.is_null() {
        return pivot;
    } else {
        return more_list_end;
    };
}
#[no_mangle]
pub extern "C" fn slist_sort(mut list: *mut *mut SListEntry, mut compare_func: SListCompareFunc) {
    slist_sort_internal(list, compare_func);
}
#[no_mangle]
pub extern "C" fn slist_find_data(
    mut list: *mut SListEntry,
    mut callback: SListEqualFunc,
    mut data: SListValue,
) -> *mut SListEntry {
    let mut rover: *mut SListEntry = 0 as *mut SListEntry;
    rover = list;
    while !rover.is_null() {
        if (unsafe { callback.expect("non-null function pointer")((*rover).data, data) })
            != 0
        {
            return rover;
        }
        rover = unsafe { (*rover).next };
    }
    return 0 as *mut SListEntry;
}
#[no_mangle]
pub extern "C" fn slist_iterate(mut list: *mut *mut SListEntry, mut iter: *mut SListIterator) {
    (unsafe { (*iter).prev_next = list });
    (unsafe { (*iter).current = 0 as *mut SListEntry });
}
#[no_mangle]
pub extern "C" fn slist_iter_has_more(mut iter: *mut SListIterator) -> i32 {
    if (unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next })
    {
        return ((unsafe { *(*iter).prev_next }) != core::ptr::null_mut() as *mut SListEntry)
            as i32;
    } else {
        return ((unsafe { (*(*iter).current).next }) != core::ptr::null_mut() as *mut SListEntry)
            as i32;
    };
}
#[no_mangle]
pub extern "C" fn slist_iter_next(mut iter: *mut SListIterator) -> SListValue {
    if (unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next })
    {
        (unsafe { (*iter).current = *(*iter).prev_next });
    } else {
        (unsafe { (*iter).prev_next = &mut (*(*iter).current).next });
        (unsafe { (*iter).current = (*(*iter).current).next });
    }
    if (unsafe { (*iter).current }).is_null() {
        return core::ptr::null_mut();
    } else {
        return unsafe { (*(*iter).current).data };
    };
}
#[no_mangle]
pub extern "C" fn slist_iter_remove(mut iter: *mut SListIterator) {
    if !((unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next }))
    {
        (unsafe { *(*iter).prev_next = (*(*iter).current).next });
        (unsafe { free((*iter).current as *mut ()) });
        (unsafe { (*iter).current = 0 as *mut SListEntry });
    }
}
